

package com.userdemo.demo.aspect;

import com.alibaba.fastjson.JSONObject;
import com.userdemo.demo.annotation.SysLog;
import com.userdemo.demo.base.BaseService;
import com.userdemo.demo.constant.base.Const;
import com.userdemo.demo.entity.base.vo.BaseUserVO;
import com.userdemo.demo.util.base.StringUtil;
import com.userdemo.demo.util.base.ToolUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;


@Aspect
@Order(5)
@Component
public class WebLogAspect extends BaseService {

    private ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Autowired
    private RedisTemplate redisTemplate;

    private Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    @Pointcut("execution(* com.userdemo.demo.service..*.*(..))")
    public void webLog(){}

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        startTime.set(System.currentTimeMillis());
        if(null ==  RequestContextHolder.getRequestAttributes()){
            return;
        }
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(null == attributes){
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        if(null == request){
            return;
        }
        HttpSession session = (HttpSession) attributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
        logger.info(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info(request.getMethod());
        //获取传入目标方法的参数
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            Object o = args[i];
            if(o instanceof ServletRequest || (o instanceof ServletResponse) || o instanceof MultipartFile){
                args[i] = o.toString();
            }
        }
        //默认关闭存储出参及入参
        String str = JSONObject.toJSONString(args);
        //请求内容
        logger.info("请求内容："+str);
        String ip = ToolUtil.getClientIp(request);
        if("0.0.0.0".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip) || "localhost".equals(ip) || "127.0.0.1".equals(ip)){
            ip = "127.0.0.1";
        }
        logger.info("请求IP："+ip);
        logger.info("请求地址"+request.getRequestURL().toString());
        if(session != null){
            logger.info("sessionID："+session.getId());
        }
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysLog mylog = method.getAnnotation(SysLog.class);
        if(mylog != null){
            //注解上的描述
            logger.info(mylog.value());
        }
        //Map<String,String> browserMap = ToolUtil.getOsAndBrowserInfo(request);
        //logger.info("浏览器类型："+browserMap.get("os")+"-"+browserMap.get("browser"));
        logger.info(ToolUtil.isAjax(request)?"请求类型："+"Ajax请求":"请求类型："+"普通请求");
        //获取缓存用户信息
        String loginToken = request.getParameter(Const.LOGINTOKEN);
        if(StringUtil.isNotEmpty(loginToken)){
            Object oUser =  redisTemplate.opsForValue().get(loginToken);
            BaseUserVO user;
            if(null != oUser) {
                user = (BaseUserVO) oUser;
                logger.info("用户信息："+user.toString());
            }
        }
    }

    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        try {
            Object obj = proceedingJoinPoint.proceed();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) {
        if(StringUtil.isEmpty(ret)){
            return;
        }
        logger.info("返回参数："+JSONObject.toJSONString(ret));
    }
}





